﻿namespace LeadMaster.Controllers
{
    using System;
    using System.Data.Entity;
    using System.Linq;
    using System.Web.Mvc;
    using LeadMaster.DAL;
    using LeadMaster.ViewModels;
    using System.Web.Security;
    using LeadMaster.Helpers;
    using System.Collections.Generic;
    using LeadMaster.Models;
    using System.Data;
    using LeadMaster.Properties;
    using System.Web;
    using System.IO;
    using System.Data.Entity.Core;

    public class QCController : Controller
    {
        private DunsmoreContext db = new DunsmoreContext();

        public ActionResult Index(string Mode="Normal")
        {
          ViewModelQC viewModel = new ViewModelQC();
          var qcFlags = new List<int>();
          switch (Mode)
          {
            case "Normal" :
              qcFlags.Add(8);
              Maintenance.inRecallMode = false;
              viewModel.Mode='N' ; // normal
              break;
            case "Pending" :
              qcFlags.Add(10);
              Maintenance.inRecallMode = false;
              viewModel.Mode = 'P'; // pending
              break;
            default:
              qcFlags.Add(2);
              qcFlags.Add(5);
              qcFlags.Add(6);
              qcFlags.Add(8);
              qcFlags.Add(10);
              Maintenance.inRecallMode = true;
              viewModel.Mode = 'R';  // recall
              break;
          }
          var validLeads = db.Leads
               .Join(db.LeadStatus, a => a.LeadID, b => b.LeadID, (a, b) => new { a, b })
               .Where(m => qcFlags.Contains(m.b.LeadFlagsID))
               .Where(m => m.a.IntRef.Trim().Length > 0)
               .OrderBy(m => m.a.IntRef)
               .Select(m => new { m.a.LeadID, m.a.IntRef })
               .Distinct();
          ViewBag.LeadClient = new SelectList(validLeads , "LeadID", "IntRef");
          var leadDates = from ls in db.LeadStatus 
                          where ls.LeadID == validLeads.FirstOrDefault().LeadID
                          where ls.LeadFlag.WithDunsmoreQC != null
                          where qcFlags.Contains(ls.LeadFlagsID)
                          select new { ls.LeadDate };

          var lds = (from ld in leadDates.AsEnumerable()
                     select new { easyDate=ld.LeadDate, orderDate = ld.LeadDate.Substring(6, 4) + ld.LeadDate.Substring(3, 2) + ld.LeadDate.Substring(0, 2) })
                              .Distinct()
                              .OrderBy(m => Convert.ToDateTime(m.easyDate)) ;

          ViewBag.LeadDate = new SelectList(lds.OrderBy(m => m.orderDate), "easyDate", "easyDate");
          viewModel.LeadDate = DateTime.Now.ToShortDateString();

          return View(viewModel);
        }

        public JsonResult LoadDates(int leadid,string Mode)
        {
          var qcFlags = new List<int>();
          switch (Mode)
          {
            case "N":
              qcFlags.Add(8);
              break;
            case "P":
              qcFlags.Add(10);
              break;
            default:
              qcFlags.Add(2);
              qcFlags.Add(5);
              qcFlags.Add(6);
              qcFlags.Add(8);
              qcFlags.Add(10);
              break;
          }
          var leadDates = from ls in db.LeadStatus
                          where ls.LeadID == leadid
                          where ls.LeadFlag.WithDunsmoreQC != null
                          where qcFlags.Contains(ls.LeadFlagsID)
                          select new {  ls.LeadDate };

          var lds = (from ld in leadDates.AsEnumerable()
                      select new { easyDate = ld.LeadDate, orderDate = ld.LeadDate.Substring(6, 4) + ld.LeadDate.Substring(3, 2) + ld.LeadDate.Substring(0, 2) })
                            .Distinct()
                            .OrderBy(m => Convert.ToDateTime(m.easyDate));

          return Json(lds, JsonRequestBehavior.AllowGet);
        }


        [HttpPost]
        public ActionResult Index(ViewModelQC viewModel)
        {
            return RedirectToAction("ShowLeads", viewModel);
        }

        private int GetID()
        {
          Guid currentUser = (Guid)Membership.GetUser().ProviderUserKey;
          int clientID = db.ClientUsers.Where(m => m.UserID == currentUser).Select(m => m.CompanyID).FirstOrDefault();
          return clientID;
        }



        public ActionResult ChangeLeadStatus(int id)
        {
          LeadResults leadResult = db.LeadResults.Find(id);

          LeadStatus leadStatus = db.LeadStatus.Where(m => m.LeadID == leadResult.LeadID && m.BlockID == leadResult.BlockId).FirstOrDefault();
          if (Roles.GetRolesForUser(User.Identity.Name).Contains(ApplicationRoles.QC))
          {
            ViewBag.LeadFlagsID = new SelectList(db.LeadFlags.Where(m => m.WithDunsmoreQC == true && m.ShowInMenu!=null), "LeadFlagsID", "Description");
          }
          ViewBag.LeadResultsID = id;
          return PartialView(leadStatus);
        }

        [HttpPost]
        public void SaveLeadStatus(LeadStatus leadStatus, FormCollection formValues)
        {
          // see what the old status was
          int oldFlagsID =Convert.ToInt16(formValues["hdnOldFlagsid"]);
          db.Entry(leadStatus).State = EntityState.Modified;
          db.SaveChanges();
          ViewModelQC viewModel = new ViewModelQC();
          viewModel.Leads = db.Leads.Find(leadStatus.LeadID);
          viewModel.LeadClient = leadStatus.LeadID;
          viewModel.LeadDate = leadStatus.LeadDate;
          //return RedirectToAction("ShowLeads", viewModel);
        }

        public JsonResult UpdateStatus(string leadStatusID)
        {
          int LeadStatusID = Convert.ToInt16(leadStatusID);
          LeadStatus leadStatus = db.LeadStatus.Where(m => m.LeadStatusID == LeadStatusID).FirstOrDefault();
          LeadStatusResponse leadStatusResponse = new LeadStatusResponse();
          leadStatusResponse.Status = leadStatus.LeadFlag.Description;
          return Json(leadStatusResponse, JsonRequestBehavior.AllowGet);
        }

        public ActionResult ChangeLeadReason(int id)
        {
          LeadResults leadResult = db.LeadResults.Find(id);
          LeadStatus leadStatus = db.LeadStatus.Where(m => m.LeadID == leadResult.LeadID && m.BlockID == leadResult.BlockId).FirstOrDefault();
          
          if (Roles.GetRolesForUser(User.Identity.Name).Contains(ApplicationRoles.QC))
          {
            ViewBag.QCLeadReasonsID = db.LeadReasons.Where(m => m.QCReasons == true).Where(m => m.Description!= "Mandatory information wrong").OrderBy(m => m.DisplayOrder).ToList();
          }

          int leadTemplateID=db.Leads.Find(leadStatus.LeadID).LeadTemplateID ?? 0;

          List<string> statMandQuestions = (from ls in db.LeadStatQuestions
                                           join lt in db.LeadStat on ls.LeadStatID equals lt.LeadStatID
                                           join t in db.LeadTemplate on lt.LeadTemplateID equals t.LeadTemplateID
                                           where t.LeadTemplateID==leadTemplateID && ls.Mandatory==true
                                           select ls.Question).ToList();


          List<string> groupMandQuestions = (from lgq in db.LeadGroupQuestions
                                            join lg in db.LeadGroups on lgq.LeadGroupsID equals lg.LeadGroupsID
                                            join t in db.LeadTemplate on lg.LeadTemplateID equals t.LeadTemplateID
                                            where t.LeadTemplateID==leadTemplateID && lgq.Mandatory==true
                                            select lgq.Question).ToList();

          List<string> qualifyingQuestions = (from lrs in db.LeadResults
                                              join lgq in db.LeadGroupQuestions on lrs.LeadGroupQuestionsID equals lgq.LeadGroupQuestionsID
                                              join lg in db.LeadGroups on lgq.LeadGroupsID equals lg.LeadGroupsID
                                              where lrs.LeadID == leadResult.LeadID && lrs.BlockId == leadResult.BlockId && lg.QualifyingGroup != null && lrs.Answer != null && lrs.Answer != "No"
                                              select lrs.Question).ToList();

          List<string> ListMandQuestions = new List<string>();
          foreach (var item in statMandQuestions)
          {
            ListMandQuestions.Add(item);
          }
          foreach (var item in groupMandQuestions)
          {
            ListMandQuestions.Add(item);
          }
          foreach (var item in qualifyingQuestions)
          {
            ListMandQuestions.Add(item);
          }

          ViewBag.QCManfield = ListMandQuestions;
          return PartialView(leadStatus);
        }

        [HttpPost]
        public void ChangeLeadReason(LeadStatus leadStatus, string newnote)
        {
          string OurReason = string.Empty;
          if (leadStatus.QCManfield != "0")
          {
            // Selected an internal mandatory field
            leadStatus.QCLeadReasonsID = db.LeadReasons.Where(m => m.Description == "Mandatory information wrong").FirstOrDefault().LeadReasonsID;
            OurReason = leadStatus.QCManfield;
          }
          else if(leadStatus.QCLeadReasonsID>1)
          {
            OurReason = db.LeadReasons.Find(leadStatus.QCLeadReasonsID).Description;
          }

          leadStatus.Notes += DateTime.Now.ToShortDateString() + " Dunsmore Notes : ";
          if (OurReason!=string.Empty)
          {
            leadStatus.Notes += "Dunsmore Reason - " + OurReason + ". " ;
          }
          leadStatus.Notes += newnote + "\n";

          ViewModelQC viewModel = new ViewModelQC();

          db.Entry(leadStatus).State = EntityState.Modified;
          db.SaveChanges();

          viewModel.LeadStatus = leadStatus;
          viewModel.LeadClient = leadStatus.LeadID;
          viewModel.Leads = db.Leads.Find(leadStatus.LeadID);
          viewModel.LeadDate = leadStatus.LeadDate;

          //return RedirectToAction("ShowLeads", viewModel);
        }

        public JsonResult UpdateReason(string leadStatusID)
        {
          int LeadStatusID = Convert.ToInt16(leadStatusID);
          LeadStatus leadStatus = db.LeadStatus.Where(m => m.LeadStatusID == LeadStatusID).FirstOrDefault();
          LeadReasonResponse leadReasonResponse = new LeadReasonResponse();
          leadReasonResponse.theReason = leadStatus.LeadReason.Description;
          if (leadReasonResponse.theReason == "Mandatory information wrong" && leadStatus.Manfield != null)
          {
            leadReasonResponse.theReason += ". " + leadStatus.Manfield;
          }
          leadReasonResponse.theNote = db.LeadStatus.Where(m => m.LeadStatusID == LeadStatusID).FirstOrDefault().Notes;
          return Json(leadReasonResponse, JsonRequestBehavior.AllowGet);
        }

        public ActionResult ShowLeads(ViewModelQC viewModel)
        {
          var qcFlags = new List<int>();
          switch (viewModel.Mode)
          {
            case 'N':
              qcFlags.Add(8);
              break;
            case 'P':
              qcFlags.Add(10);
              break;
            default:
              qcFlags.Add(2);
              qcFlags.Add(5);
              qcFlags.Add(6);
              qcFlags.Add(8);
              qcFlags.Add(10);
              break;
          }
          viewModel.Leads = db.Leads.Where(m => m.LeadID == viewModel.LeadClient).FirstOrDefault();
          if (false && viewModel.Leads.StreetView == true)
          {
            string companyPostcode = viewModel.Leads.Company.Postcode.Replace(" ", "");
            PostCodes postCode = db.Postcodes.Where(m => m.Postcode == companyPostcode).FirstOrDefault();
            ViewBag.LatLong = string.Format("{0},{1}", postCode.lat.ToString(), postCode.longitude.ToString());
          }  
          int id = GetID();
          List<LeadResults> leadResults = db.LeadResults
            .Join(db.LeadStatus, a => a.LeadID, b => b.LeadID, (a, b) => new { a, b })
            .Where(m => m.a.LeadID == m.b.LeadID && m.a.BlockId == m.b.BlockID)
            .Where(m => m.a.LeadID == viewModel.Leads.LeadID)
            .Where(m => m.a.LeadStatQuestionsID != null)
            .Where(m => m.b.LeadDate==viewModel.LeadDate)
            .Where(m => qcFlags.Contains(m.b.LeadFlagsID))
            .Select(m => m.a)
            .OfType<LeadResults>()
            .ToList();
          int blockID = 0;
          LeadStatus statusBlock = db.LeadStatus.FirstOrDefault();
          LeadFlags leadFlag = db.LeadFlags.FirstOrDefault();
          LeadReasons leadReason = db.LeadReasons.FirstOrDefault();
          string qcReason=string.Empty;
          viewModel.FullListLeadResults = new List<ListLeadResults>();
          int totalLeads = 0;
          int firstQuestion = 0;
          int questionBlock = 0;
          foreach (LeadResults item in leadResults)
          {
            ListLeadResults listLeadResults = new ListLeadResults();
            listLeadResults.LeadResult = item;
            if (item.BlockId != blockID)
            {
                firstQuestion = firstQuestion==0 ? item.BlockId : firstQuestion;

                statusBlock = db.LeadStatus
                    .Where(m => m.LeadID == item.LeadID && m.BlockID == item.BlockId)
                    .FirstOrDefault();
                leadFlag = db.LeadFlags.Find(statusBlock.LeadFlagsID);
                leadReason = db.LeadReasons.Find(statusBlock.LeadReasonsID);
                qcReason = statusBlock.QCLeadReasonsID==null ? string.Empty : db.LeadReasons.Find(statusBlock.QCLeadReasonsID).Description;
                totalLeads++;
            }
            if (firstQuestion == item.BlockId)
            {
                questionBlock++;
            }
            blockID = item.BlockId;
            listLeadResults.LeadFlag = leadFlag;
            listLeadResults.LeadReason = leadReason;
            listLeadResults.LeadStatus = statusBlock;
            listLeadResults.QCReason = qcReason;
            viewModel.FullListLeadResults.Add(listLeadResults);
          }
          viewModel.QuestionBlock = questionBlock;
          // Title Generation for the table
          viewModel.Titles = new List<string>();
          if (viewModel.FullListLeadResults.Count() > 0)
          {
            int questionCounter = 0;
            foreach (var item in leadResults)
            {
              viewModel.Titles.Add(item.Question);
              questionCounter++;
              if (questionCounter == questionBlock)
              {
                questionCounter = 0;
                break;
              }
            }
          }
          ViewBag.TotalLeads = totalLeads;
          ViewBag.ReturnDate = DateTime.Now.AddDays(AdditionalDays.AddLeadDays(DateTime.Now.DayOfWeek)+1).ToShortDateString();
          return View(viewModel);
        }

        [HttpPost]
        public ContentResult UploadVoxFile()
        {
          var r = new List<ViewDataUploadFilesResult>();

          foreach (string file in Request.Files)
          {
            HttpPostedFileBase hpf = Request.Files[file] as HttpPostedFileBase;
            if (hpf.ContentLength == 0)
              continue;

            string savedFileName = Path.Combine(Server.MapPath("~/Vox"), Path.GetFileName(hpf.FileName));
            hpf.SaveAs(savedFileName); // Save the file

            r.Add(new ViewDataUploadFilesResult()
            {
              Name = hpf.FileName,
              Length = hpf.ContentLength,
              Type = hpf.ContentType
            });

          }
          // Returns json
          return Content("{\"name\":\"" + r[0].Name + "\",\"type\":\"" + r[0].Type + "\",\"size\":\"" + string.Format("{0} bytes", r[0].Length) + "\"}", "application/json");
        }

        [HttpPost]
        public void RegisterVoxFile(int id, string filename)
        {
            LeadResults leadResult = db.LeadResults.Find(id);
            LeadStatus leadStatus = db.LeadStatus.Where(m => m.LeadID == leadResult.LeadID && m.BlockID == leadResult.BlockId).FirstOrDefault();
            leadStatus.VoxFile = filename;
            db.Entry(leadStatus).State = EntityState.Modified;
            db.SaveChanges();
        }

        public ActionResult FetchLeadBlock(ViewModelQC viewModel)
        {
            int id = GetID();
            viewModel.Leads = db.Leads.Where(m => m.LeadID == viewModel.LeadClient).FirstOrDefault();
            var leadDates = from lr in db.LeadResults
                            join ls in db.LeadStatus on new { Key1 = lr.LeadID, Key2 = lr.BlockId } equals new { Key1 = ls.LeadID, Key2 = ls.BlockID }
                            where lr.LeadID == viewModel.Leads.LeadID
                            where ls.LeadFlag.WithDunsmoreQC != null 
                            where ls.LeadFlag.Description == "Lead Rejected"
                            select new { lr.LeadDate };

            var lds = (from ld in leadDates.AsEnumerable()
                       select new { leadtimestamp = ld.LeadDate.ToShortDateString() as string, correctDate = ld.LeadDate.Date })
                                .Distinct();
            ViewBag.LeadID = viewModel.Leads.LeadID;
            List<string> leadtimestamps = lds.OrderByDescending(m => m.correctDate).Select(m => m.leadtimestamp.ToString()).ToList();
            return View(leadtimestamps);
        }

        public ActionResult CallInfo(int leadID, int blockID)
        {
            List<LeadResults> listLeadResults = (from lr in db.LeadResults
                                                where lr.LeadID == leadID && lr.BlockId == blockID
                                                where lr.Answer!="No"
                                                select lr)
                                                .ToList();
            var returnReason = (from ls in db.LeadStatus
                                    where ls.LeadID == leadID && ls.BlockID == blockID
                                    select new { ls.LeadFlag.Description, leadReasonDescription=ls.LeadReason.Description, ls.Notes })
                                 .FirstOrDefault();

            ViewBag.ReturnReason = returnReason.Description + ":" + returnReason.leadReasonDescription + "," + returnReason.Notes;

            return PartialView(listLeadResults);
        }

        public ActionResult ClientInfo(int leadID)
        {
          Leads lead = (from l in db.Leads where l.LeadID == leadID select l).FirstOrDefault();
          string ClientInfo = lead.FreeNotes??string.Empty;
          ClientInfo += ". Territory=" + lead.Territory;
          ViewBag.ClientInfo = ClientInfo;
          return PartialView();
        }

        public static string StreetviewLatLong(int leadStatusID)
        {
          DunsmoreContext db = new DunsmoreContext();
          LeadStatus leadStatus = db.LeadStatus.Find(leadStatusID);
          string postCode = db.LeadResults
              .Where(m => m.LeadID == leadStatus.LeadID && m.BlockId == leadStatus.BlockID && m.Question == "Postcode")
              .Select(m => m.Answer)
              .FirstOrDefault();
          PostCodes postCodes = db.Postcodes.Where(m => m.Postcode == postCode.Replace(" ","")).FirstOrDefault();
          string returnString = postCodes!=null ? (postCodes.lat.ToString() + "," + postCodes.longitude.ToString()) : string.Empty; 
          return returnString;
        }

        public static string StreetviewPostcode(int leadStatusID)
        {
          DunsmoreContext db = new DunsmoreContext();
          LeadStatus leadStatus = db.LeadStatus.Find(leadStatusID);
          string postCode = db.LeadResults
              .Where(m => m.LeadID == leadStatus.LeadID && m.BlockId == leadStatus.BlockID && m.Question == "Postcode")
              .Select(m => m.Answer)
              .FirstOrDefault();
          string returnString =  postCode;
          return returnString;
        }

        public void DunsmoreQCD(string leadID, string blockID)
        {
          int leadid = Convert.ToInt16(leadID);
          int blockid = Convert.ToInt16(blockID);
          LeadStatus leadStatus = db.LeadStatus.Where(m => m.LeadID == leadid && m.BlockID==blockid).FirstOrDefault();
          leadStatus.DunsmorePreCheck = true;
          leadStatus.LeadFlagsID = 2;
          leadStatus.LeadDate = DateTime.Now.ToShortDateString();
          db.Entry(leadStatus).State = EntityState.Modified;
          db.SaveChanges();
          // has client asked for email notification
          Leads lead = db.Leads.Find(leadid);
          if (lead.NewLeadAlert == true)
          {
              List<LeadResults> lrs = db.LeadResults.Where(m => m.LeadID == leadid && m.BlockId == blockid).ToList();
              List<Contacts> recipients = db.Contacts
                            .Join(db.Companies, a => a.CompanyID, b => b.CompanyID, (a, b) => new { a, b })
                            .Where(m => m.a.CompanyID == m.b.CompanyID)
                            .Where(m => m.a.CompanyID == lead.CompanyID)
                            .Select(m => m.a)
                            .ToList();
              OracMailMessage mm = new OracMailMessage();
              mm.EmailSubject = "We have just uploaded a new lead for you under the reference " + lead.IntRef;
              string LeadDetails = string.Format("{0}", Environment.NewLine);
              LeadDetails += string.Format("Please contact this lead as soon as possible as they have just been qualified as a possible candidate for your scheme.{0}", Environment.NewLine);
              LeadDetails += string.Format("{0}", Environment.NewLine);
              LeadDetails += string.Format("Lead Details{0}", Environment.NewLine);
              LeadDetails += string.Format("{0}", Environment.NewLine);
              foreach (var item in lrs)
              {
                  if (item.Answer != null)
                  {
                      LeadDetails += string.Format("{0} - {1}{2}", item.Question, item.Answer ?? string.Empty, Environment.NewLine);
                      LeadDetails += (item.Question + item.Answer).Length > 30 ? Environment.NewLine : string.Empty;
                  }
              }
              LeadDetails += string.Format("{0}", Environment.NewLine);
              LeadDetails += string.Format("{0}This is an automated email from Orac, please do not Reply. Please tell Orac the status of this lead after you have processed it. Thank you.", Environment.NewLine);
              foreach (var contact in recipients)
              {
                  if (contact.LLN == true && contact.Email != null)
                  {

                      mm.EmailTo = contact.Email;
                      mm.EmailBody = string.Format("Hello " + contact.Forename + ", greetings from Orac.{0}", Environment.NewLine);
                      mm.EmailBody += LeadDetails;
                      mm.SendEmail();
                  }
              }
          }
        }

        public void DunsmoreReject(int leadID, int blockID)
          {
            LeadStatus leadStatus = db.LeadStatus.Where(m => m.LeadID == leadID && m.BlockID==blockID).FirstOrDefault();
            leadStatus.DunsmorePreCheck = false;
            leadStatus.LeadFlagsID = 5;
            db.Entry(leadStatus).State = EntityState.Modified;
            db.SaveChanges();
          }

        public ActionResult QCOrder()
        {
          Maintenance.inMaintenance = true;
          var query = "exec QCOrder";
          GenericRepository gr = new GenericRepository();
          IEnumerable<QCOrder> QCOrderList = gr.GetQCOrder(query);
          return View(QCOrderList);
        }

        public ActionResult ProcessQCOrder(string leadDate, int leadid)
        {
          ViewModelQC viewModel = new ViewModelQC();
          viewModel.LeadClient=leadid;
          viewModel.LeadDate = leadDate;          
          return RedirectToAction("ShowLeads", viewModel);
        }

        public ActionResult EditLeadStatus(int leadStatusID)
        {
          LeadStatus leadStatus = db.LeadStatus.Find(leadStatusID);

          return View(leadStatus);
        }

        [HttpPost]
        public ActionResult EditLeadStatus(LeadStatus leadStatus)
        {
          db.Entry(leadStatus).State = EntityState.Modified;
          db.SaveChanges();

          return RedirectToAction("Index");
        }

        public ActionResult EditLeadResults(int leadStatusID)
        {
          LeadStatus ls=db.LeadStatus.Find(leadStatusID);
          List<LeadResults> leadresults = db.LeadResults.Where(m => m.LeadID == ls.LeadID && m.BlockId == ls.BlockID).ToList();

          return View(leadresults);
        }

        [HttpPost]
        public ActionResult EditLeadResults(List<LeadResults> listLeadResults)
        {
          foreach (LeadResults item in listLeadResults)
          {
            db.Entry(item).State = EntityState.Modified;
          }
          db.SaveChanges();

          return RedirectToAction("Index");
        }
    }
  }
